package online.shuita.gitee.mojo.generator;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import lombok.extern.slf4j.Slf4j;
import online.shuita.gitee.mojo.model.*;
import org.apache.commons.lang3.StringUtils;

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Slf4j
public abstract class AbsGenerator implements IGenerator {
    protected Map<String, String> doGenerateDoc(AnalyResult analyResult) {
        //输出对象
        Map<String, StringBuffer> outMap = Maps.newHashMap();

        List<IntfModel> intfList = analyResult.getIntfModelList();
        Map<String, List<IntfModel>> intfMap = intfList.stream().collect(Collectors.groupingBy(IntfModel::getDomain));
        intfMap.entrySet().forEach(entry -> {
            String domain = entry.getKey() + "";
            if (!outMap.containsKey(domain)) {
                outMap.putIfAbsent(domain, new StringBuffer());
            }
            StringBuffer outBuffer = outMap.get(domain);

            try {
                outBuffer.append(String.format("# %s接口清单  \n", domain));
                outBuffer.append("| 序号 | 接口 | 中文名 | 备注 |  \n");
                outBuffer.append("| --- | --- | --- | --- |  \n");

                List<IntfModel> sublist = entry.getValue();
                //输出接口清单
                for (int idx = 0; idx < sublist.size(); idx++) {
                    IntfModel intf = sublist.get(idx);
                    outBuffer.append(String.format("| %s | %s | %s | %s |  \n", idx + 1, converterHtmlStr(intf.getIntfShortName()), StringUtils.trimToEmpty(intf.getIntfDesc()), ""));
                }
                //输出接口详情
                for (int idx = 0; idx < sublist.size(); idx++) {
                    IntfModel intf = sublist.get(idx);
                    outBuffer.append(String.format("### <span id=\"anchor%s\" name=\"anchor%s\">%s、%s</span>  \n", idx + 1, idx + 1, idx + 1, converterHtmlStr(intf.getIntfShortName())));

                    List<MethodModel> methodModelList = intf.getMethodModelList();

                    for (int midx = 0; midx < methodModelList.size(); midx++) {
                        generateMethodDoc(idx, midx, methodModelList.get(midx), outBuffer, analyResult.getPojoModelMap());
                    }
                }
            } catch (Throwable e) {
                log.error("输出文档失败", e);
            }
        });

        //输出对象
        Map<String, String> resultMap = Maps.newHashMap();
        outMap.entrySet().forEach(entry -> {
            resultMap.putIfAbsent(entry.getKey(), entry.getValue().toString());
        });
        return resultMap;
    }

    private void generateMethodDoc(int intfIdx, int methodIdx, MethodModel methodModel, StringBuffer outBuffer, Map<String, List<PojoModel>> pojoModelMap) {
        try {
            outBuffer.append(String.format("#### %s.%s、%s%s%s  \n", intfIdx + 1, methodIdx + 1, methodModel.getDeprecated() ? "<del>" : "", converterHtmlStr(methodModel.getMethodShortName()), methodModel.getDeprecated() ? "</del>" : ""));
            outBuffer.append("**接口名：**  \n");
            outBuffer.append(String.format("%s  \n", converterHtmlStr(methodModel.getMethodName())));
            outBuffer.append("**接口说明：**  \n");
            outBuffer.append(String.format("%s  \n", StringUtils.trimToEmpty(methodModel.getMethodDesc())));
            outBuffer.append("**入参：**  \n");
            //输出入参表格：
            outBuffer.append("<table>");
            //输出表头
            outBuffer.append("<tr><th>字段名</th><th>类型</th><th>是否必填</th><th>字段描述</th></tr>");
            //输出字段
            List<ParameterModel> paramList = methodModel.getParameterModelList();
            List<PojoModel> pojoModelList = Lists.newArrayList();

            for (int pidx = 0; pidx < paramList.size(); pidx++) {
                ParameterModel parm = paramList.get(pidx);
                outBuffer.append(String.format("<tr><td>%s</td><td>%s</td><td>%s</td><td>%s</td></tr>",
                        converterHtmlStr(parm.getParameterName()), converterHtmlStr(parm.getTypeShotName()), "", StringUtils.trimToEmpty(parm.getDesc())));
                if (pojoModelMap.containsKey(parm.getGenericType())) {
                    pojoModelList.addAll(pojoModelMap.get(parm.getGenericType()));
                }
            }

            //输出其他pojo
            if (null != pojoModelList) {
                List<String> generatePojo = Lists.newArrayList();
                generatePojoDoc(pojoModelList.stream().distinct().collect(Collectors.toList()),
                        outBuffer, pojoModelMap, generatePojo);
            }

            outBuffer.append("</table>\n\n");

            outBuffer.append("**出参：**  \n");
            //输出入参表格：
            outBuffer.append("<table>\n");
            //输出表头
            outBuffer.append("<tr><th>字段名</th><th>类型</th><th>是否必填</th><th>字段描述</th></tr>\n");
            //输出字段
            List<PojoModel> outPojoModelList = Lists.newArrayList();
            if (pojoModelMap.containsKey(methodModel.getReturnGenericType())) {
                outPojoModelList.addAll(pojoModelMap.get(methodModel.getReturnGenericType()));
            } else {
                outBuffer.append(String.format("<tr><td>%s</td><td>%s</td><td>%s</td><td>%s</td></tr>\n",
                        "returnValue", converterHtmlStr(methodModel.getReturnTypeShotName()), "是", ""));
            }

            //输出其他pojo
            if (null != outPojoModelList) {
                List<String> generatePojo = Lists.newArrayList();
                generatePojoDoc(outPojoModelList.stream().distinct().collect(Collectors.toList()),
                        outBuffer, pojoModelMap, generatePojo);
            }

            outBuffer.append("</table>\n\n");
        } catch (Throwable e) {
            log.error("输出文档失败", e);
        }
    }

    private void generatePojoDoc(List<PojoModel> pojoModels, StringBuffer outBuffer, Map<String, List<PojoModel>> pojoModelMap, List<String> generatePojo) {
        pojoModels.forEach(pojo -> {
            if (generatePojo.contains(pojo.getType())) {
                return;
            }
            try {
                outBuffer.append(String.format("<tr><td colspan=\"4\"><b><i>%s</i></b></td></tr>\n", converterHtmlStr(pojo.getShortType())));

                List<FieldModel> paramList = pojo.getFieldEntryList();
                List<PojoModel> pojoModelList = Lists.newArrayList();

                for (int pidx = 0; pidx < paramList.size(); pidx++) {
                    FieldModel parm = paramList.get(pidx);
                    outBuffer.append(String.format("<tr><td>%s%s%s</td><td>%s</td><td>%s</td><td>%s</td></tr>\n",
                            parm.getDeprecated() ? "<del>" : "", converterHtmlStr(parm.getName()), parm.getDeprecated() ? "</del>" : "", converterHtmlStr(parm.getShortType()), "", StringUtils.trimToEmpty(parm.getDesc())));
                    if (pojoModelMap.containsKey(parm.getGenericType())) {
                        pojoModelList.addAll(pojoModelMap.get(parm.getGenericType()));
                    }
                }
                generatePojo.add(pojo.getType());

                //输出其他pojo
                if (null != pojoModelList && pojoModelList.size() > 0) {
                    generatePojoDoc(pojoModelList.stream().distinct().collect(Collectors.toList()),
                            outBuffer, pojoModelMap, generatePojo);
                }
            } catch (Throwable e) {
                log.error("输出文档失败", e);
            }
        });
    }

    private String converterHtmlStr(String str) {
        return str.replaceAll("<=", "<= &le;").replaceAll(">=", "&ge;").replaceAll("<", "&lt;").replaceAll(">", "&gt;");
    }
}
